畫面組裝的藍圖:component 初探
component
簡單來說就是畫面的藍圖,component 就是由開發者自行定義好的商業邏輯、特定的樣式、React Element 畫面所組成的,就如同蓋房子一樣,如果說應用程式是一棟房子,那麼 component 就是搭建成房子的不同建材:鋼筋、水泥、磚頭...,透過組合這些 component 而逐步組成應用程式的畫面,同時 component 是可以重複使用的,讓程式碼變得更容易維護與管理。
例如:設計一個 TodoList 的應用程式,可以將 TodoList 拆分成由多個 <TodoItem />
元件所組成的 <TodoList/>
元件,雖然 <TodoItem />
這個元件是重用的,但每一個 <TodoItem />
都有其各自的元件狀態。
const TodoItem = ({ todo }) => {
return <li>{todo}</li>;
};
const TodoList = () => {
const todos = ["Todo 1", "Todo 2", "Todo 3"];
return (
<div>
<h1>Todo List</h1>
<ul>
{todos.map((todo, index) => (
<TodoItem key={`${todo}-${index}`} todo={todo} />
))}
</ul>
</div>
);
};
props? 為什麼 props 是唯讀的?
props 指的就是呼叫 component 時會傳入 component 的屬性,而 props 的資料型別在 React 中沒有任何限制。當 component 接收到從外部傳入的 props 後,就可以根據 props 去產生相對應的客製化的畫面或是商業邏輯。
const TodoItem = ({ title, isDone }) => {
//將接收到的 props 使用解構取出屬性資料,這樣也就可以賦值到區域變數中
return(
<li>
<input type='checkbox' id={title} name={title} checked={isDone} />
<label htmlFor={title}>{title}</label>
</li>;
)
};
const TodoList = () => {
const todos = [
{
title: "Todo 1",
isDone: false,
},
{
title: "Todo 2",
isDone: true,
},
{
title: "Todo 3",
isDone: false,
},
];
return (
<div>
<h1>Todo List</h1>
<ul>
{todos.map((todo, index) => (
<TodoItem
key={`${todo}-${index}`}
title={todo.title} //將 title 屬性傳入 <TodoItem/>
isDone={todo.isDone} //將 isDone 屬性傳入 <TodoItem/>
/>
))}
</ul>
</div>
);
};
props 的特性是唯讀的,這是因為 React 的核心概念是單向資料流,所以當資料以 props 屬性傳遞到 components 內部時,為了確保資料的源頭與可追蹤性,以維持 單向資料流的特性,所以 props 是不可以被修改的,因為當 props 被手動修改時,我們就無法確定資料的來源是從哪裡來的,也可能會出現無法預期的錯誤。
component 的 render 與 re-render
component 的一次 render 指的是 react 呼叫 component function 後產生描述一段畫面的 React Element 的結果。又 react virtual dom 為樹狀資料結構,當父 component 中包含一個或是多個子 component 時,當父 component render 時,其所包含的子 component 就會跟著進行一次的 render ,將所 render 完成的 react element 裝回上一層的父 component 上,整個過程是由上而下,會一直持續遍歷到最底層的 component,最後會拼裝成一個完整樹狀結構的 react element。
re-render 則指的是當 component 的 props 或 state 資料發生變化時,react 會重新呼叫 component function 並重新 render 一次,會根據新的原始資料重新產生一份新的 react element,並透過 diff 演算法比對新舊的 react element,找出差異的部分,最後再進行 DOM 更新。
re-render 的時機點:
- component 本身
setState
更新資料 - 父層 component 資料更新傳入子 component
- Content provider 的 component 更新時